package com.pl.util;

import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Arrays;

import org.bouncycastle.crypto.DerivationParameters;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.ExtendedDigest;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.digests.ShortenedDigest;
import org.bouncycastle.crypto.generators.KDF1BytesGenerator;
import org.bouncycastle.crypto.params.ISO18033KDFParameters;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;


public class SM2Util {
    private static final BigInteger p = new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16);


    private static final BigInteger a = new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", 16);


    private static final BigInteger b = new BigInteger("28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", 16);


    private static final BigInteger xg = new BigInteger("32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", 16);


    private static final BigInteger yg = new BigInteger("BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", 16);


    private static final BigInteger n = new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16);


    private static SecureRandom random = new SecureRandom();


    private static ECCurve.Fp curve = new ECCurve.Fp(p, a, b);


    private static ECPoint G = curve.createPoint(xg, yg);


    public static BigInteger random(BigInteger max) {
        BigInteger r = new BigInteger(256, random);

        while (r.compareTo(max) >= 0) {
            r = new BigInteger(128, random);
        }

        return r;
    }

    private static boolean allZero(byte[] buffer) {
        for (int i = 0; i < buffer.length; i++) {
            if (buffer[i] != 0)
                return false;
        }
        return true;
    }


    public static String encrypt(String input, ECPoint publicKey) {
        /* 109 */
        byte[] inputBuffer = input.getBytes();


        /* 112 */
        BigInteger k = random(n);


        /* 115 */
        ECPoint C1 = G.multiply(k);
        /* 116 */
        byte[] C1Buffer = C1.getEncoded(false);










        /* 127 */
        ECPoint kpb = publicKey.multiply(k).normalize();


        /* 130 */
        byte[] kpbBytes = kpb.getEncoded(false);
        /* 131 */
        KDF1BytesGenerator kDF1BytesGenerator = new KDF1BytesGenerator((Digest) new ShortenedDigest((ExtendedDigest) new SHA256Digest(), 20));

        /* 133 */
        byte[] t = new byte[inputBuffer.length];
        /* 134 */
        kDF1BytesGenerator.init((DerivationParameters) new ISO18033KDFParameters(kpbBytes));
        /* 135 */
        kDF1BytesGenerator.generateBytes(t, 0, t.length);






        /* 142 */
        byte[] C2 = new byte[inputBuffer.length];
        /* 143 */
        for (int i = 0; i < inputBuffer.length; i++) {
            /* 144 */
            C2[i] = (byte) (inputBuffer[i] ^ t[i]);
        }


        /* 148 */
        byte[] C3 = calculateHash(kpb.getXCoord().toBigInteger(), inputBuffer, kpb
/* 149 */.getYCoord().toBigInteger());


        /* 152 */
        byte[] encryptResult = new byte[C1Buffer.length + C2.length + C3.length];
        /* 153 */
        System.arraycopy(C1Buffer, 0, encryptResult, 0, C1Buffer.length);
        /* 154 */
        System.arraycopy(C2, 0, encryptResult, C1Buffer.length, C2.length);
        /* 155 */
        System.arraycopy(C3, 0, encryptResult, C1Buffer.length + C2.length, C3.length);


        /* 158 */
        return bytes2HexString(encryptResult);
    }

    public static String decrypt(String encryptDataStr, BigInteger privateKey) {
        /* 162 */
        byte[] encryptData = hexString2Bytes(encryptDataStr);
        /* 163 */
        byte[] C1Byte = new byte[65];
        /* 164 */
        System.arraycopy(encryptData, 0, C1Byte, 0, C1Byte.length);

        /* 166 */
        ECPoint C1 = curve.decodePoint(C1Byte).normalize();


        /* 169 */
        ECPoint dBC1 = C1.multiply(privateKey).normalize();


        /* 172 */
        byte[] dBC1Bytes = dBC1.getEncoded(false);
        /* 173 */
        KDF1BytesGenerator kDF1BytesGenerator = new KDF1BytesGenerator((Digest) new ShortenedDigest((ExtendedDigest) new SHA256Digest(), 20));


        /* 176 */
        int klen = encryptData.length - 65 - 20;

        /* 178 */
        byte[] t = new byte[klen];
        /* 179 */
        kDF1BytesGenerator.init((DerivationParameters) new ISO18033KDFParameters(dBC1Bytes));
        /* 180 */
        kDF1BytesGenerator.generateBytes(t, 0, t.length);






        /* 187 */
        byte[] M = new byte[klen];
        /* 188 */
        for (int i = 0; i < M.length; i++) {
            /* 189 */
            M[i] = (byte) (encryptData[C1Byte.length + i] ^ t[i]);
        }


        /* 193 */
        byte[] C3 = new byte[20];
        /* 194 */
        System.arraycopy(encryptData, encryptData.length - 20, C3, 0, 20);
        /* 195 */
        byte[] u = calculateHash(dBC1.getXCoord().toBigInteger(), M, dBC1
/* 196 */.getYCoord().toBigInteger());
        /* 197 */
        if (Arrays.equals(u, C3)) {
            /* 198 */
            return new String(M);
        }
        /* 200 */
        return null;
    }


    private static byte[] calculateHash(BigInteger x2, byte[] M, BigInteger y2) {
        /* 205 */
        ShortenedDigest digest = new ShortenedDigest((ExtendedDigest) new SHA256Digest(), 20);
        /* 206 */
        byte[] buf = x2.toByteArray();
        /* 207 */
        digest.update(buf, 0, buf.length);
        /* 208 */
        digest.update(M, 0, M.length);
        /* 209 */
        buf = y2.toByteArray();
        /* 210 */
        digest.update(buf, 0, buf.length);

        /* 212 */
        buf = new byte[20];
        /* 213 */
        digest.doFinal(buf, 0);
        /* 214 */
        return buf;
    }

    private static boolean between(BigInteger param, BigInteger min, BigInteger max) {
        /* 218 */
        if (param.compareTo(min) >= 0 && param.compareTo(max) < 0) {
            /* 219 */
            return true;
        }
        /* 221 */
        return false;
    }


    private static boolean checkPublicKey(ECPoint publicKey) {
        /* 231 */
        if (!publicKey.isInfinity()) {
            /* 232 */
            BigInteger x = publicKey.getXCoord().toBigInteger();
            /* 233 */
            BigInteger y = publicKey.getYCoord().toBigInteger();
            /* 234 */
            if (between(x, new BigInteger("0"), p) && between(y, new BigInteger("0"), p)) {
                /* 235 */
                BigInteger xResult = x.pow(3).add(a.multiply(x)).add(b).mod(p);
                /* 236 */
                BigInteger yResult = y.pow(2).mod(p);
                /* 237 */
                if (yResult.equals(xResult) && publicKey.multiply(n).isInfinity()) {
                    /* 238 */
                    return true;
                }
            }
            /* 241 */
            return false;
        }
        /* 243 */
        return false;
    }


    public static byte[] hexStringToBytes(String hexString) {
        /* 262 */
        if (hexString == null || hexString.equals("")) {
            /* 263 */
            return null;
        }
        /* 265 */
        hexString = hexString.toUpperCase();
        /* 266 */
        int length = hexString.length() / 2;
        /* 267 */
        char[] hexChars = hexString.toCharArray();
        /* 268 */
        byte[] d = new byte[length];
        /* 269 */
        for (int i = 0; i < length; i++) {
            /* 270 */
            int pos = i * 2;
            /* 271 */
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
        }

        /* 274 */
        return d;
    }

    private static byte charToByte(char c) {
        /* 278 */
        return (byte) "0123456789ABCDEF".indexOf(c);
    }


    public static String bytes2HexString(byte[] b) {
        /* 283 */
        StringBuffer result = new StringBuffer();
        /* 284 */
        for (int i = 0; i < b.length; i++) {
            /* 285 */
            result.append(String.format("%02X", new Object[]{Byte.valueOf(b[i])}));
        }
        /* 287 */
        return result.toString();
    }


    public static byte[] hexString2Bytes(String src) {
        /* 298 */
        int l = src.length() / 2;
        /* 299 */
        byte[] ret = new byte[l];
        /* 300 */
        for (int i = 0; i < l; i++) {
            /* 301 */
            ret[i] = Integer.valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();
        }
        /* 303 */
        return ret;
    }

    public static ECPoint getPublicKey(BigInteger privateKey) {
        /* 307 */
        return G.multiply(privateKey).normalize();
    }
}


/* Location:              E:\code\common\cmsr-common-mybatis\1.0.0-SNAPSHOT\cmsr-common-mybatis-1.0.0-SNAPSHOT.jar!\com\cmsr\common\mybati\\util\SM2Util.class
 * Java compiler version: 8 (52.0)
 * JD-Core Version:       1.1.3
 */